package com.pig4cloud.pig.ads.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpHeaders;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/**
 * @author zxm
 * @投放平台http 请求工具类
 */
@Slf4j
public class OEHttpUtils {

	// private static final String[] TLS_VERSION = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
	private static final String[] TLS_VERSION = {"TLSv1.2"};

	@SneakyThrows
	public static String doPost(String url, Map<String, Object> data) {

		// 构造请求
		HttpPost httpEntity = new HttpPost(url);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;

		try {
			SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(SSLContexts.createDefault(), TLS_VERSION, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			client = HttpClientBuilder.create().setSSLSocketFactory(ssl).build();
			httpEntity.setEntity(new StringEntity(JSONObject.toJSONString(data), ContentType.APPLICATION_JSON));

			response = client.execute(httpEntity);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuilder result = new StringBuilder();
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return UicodeBackslashUtils.unicodeToCn(result.toString());
			}

		} finally {
			if (response != null) {
				response.close();
			}
			if (null != client) {
				client.close();
			}
		}
		return null;
	}

	@SneakyThrows
	public static String doPost(String url, Map<String, Object> data, String access_token) {

		// 构造请求
		HttpPost httpEntity = new HttpPost(url);
		httpEntity.setHeader("Access-Token", access_token);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;

		try {
			SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(SSLContexts.createDefault(), TLS_VERSION, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			client = HttpClientBuilder.create().setSSLSocketFactory(ssl).build();
			httpEntity.setEntity(new StringEntity(JSONObject.toJSONString(data), ContentType.APPLICATION_JSON));

			response = client.execute(httpEntity);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuilder result = new StringBuilder();
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return UicodeBackslashUtils.unicodeToCn(result.toString());
			}

		} finally {
			if (response != null) {
				response.close();
			}
			if (null != client) {
				client.close();
			}
		}
		return null;
	}

	@SneakyThrows
	public static String doGet(String url, Map<String, Object> data, String access_token) {

		// 构造请求
		HttpEntityEnclosingRequestBase httpEntity = new HttpGet();
		httpEntity.setHeader("Access-Token", access_token);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;

		try {
			SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(SSLContexts.createDefault(), TLS_VERSION, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			client = HttpClientBuilder.create().setSSLSocketFactory(ssl).build();
			httpEntity.setURI(URI.create(url));
			httpEntity.setEntity(new StringEntity(JSONObject.toJSONString(data), ContentType.APPLICATION_JSON));

			response = client.execute(httpEntity);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuilder result = new StringBuilder();
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return UicodeBackslashUtils.unicodeToCn(result.toString());
			}

		} finally {
			if (response != null) {
				response.close();
			}
			if (null != client) {
				client.close();
			}
		}
		return null;
	}

	/**
	 * 广点通接口
	 *
	 * @author zxm
	 */
	@SneakyThrows
	public static String doGdtGet(String url, Map<String, String> headers) {
		HttpClient client = null;
		try {
			URL urlR = new URL(url);
			URI uri = new URI(urlR.getProtocol(), urlR.getHost(), urlR.getPath(), urlR.getQuery(), null);
			client = new DefaultHttpClient();
			org.apache.http.client.methods.HttpGet get = new org.apache.http.client.methods.HttpGet(uri);
			HttpParams params = client.getParams();
			HttpConnectionParams.setConnectionTimeout(params, 10000);
			HttpConnectionParams.setSoTimeout(params, 10000);
			if (headers != null && headers.size() > 0) {
				Set<String> set = headers.keySet();
				for (String key : set) {
					get.addHeader(key, headers.get(key));
				}
			}
			HttpResponse response = client.execute(get);
			HttpEntity entity = response.getEntity();
			if (entity == null) {
				return null;
			}
			String stringResult = EntityUtils.toString(entity, "utf-8");
			return UicodeBackslashUtils.unicodeToCn(stringResult);
		} finally {
			if (client != null) {
				client.getConnectionManager().shutdown();
			}
		}
	}
	@SneakyThrows
	public static String doGetQueryString(String url, Map<String, String> param, String access_token) {

		// 构造请求
		HttpEntityEnclosingRequestBase httpEntity = new HttpEntityEnclosingRequestBase() {
			@Override
			public String getMethod() {
				return "GET";
			}
		};
		httpEntity.setHeader("Access-Token", access_token);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;

		try {
			//SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(SSLContexts.createDefault(), TLS_VERSION, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(
					SSLContexts.custom().loadTrustMaterial(null,new TrustSelfSignedStrategy()).build(), NoopHostnameVerifier.INSTANCE
			);
			client = HttpClientBuilder.create().setSSLSocketFactory(ssl).build();

			URIBuilder builder = new URIBuilder(url);
			if (param != null) {
				for (String key : param.keySet()) {
					builder.addParameter(key, param.get(key));
				}
			}
			URI uri = builder.build();
			httpEntity.setURI(uri);
			httpEntity.setConfig(RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(5000).setSocketTimeout(5*60*1000).build());

			response = client.execute(httpEntity);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuilder result = new StringBuilder();
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return UicodeBackslashUtils.unicodeToCn(result.toString());
			}

		} finally {
			if (response != null) {
				response.close();
			}
			if (null != client) {
				client.close();
			}
		}
		return null;
	}

	/**
	 * @文件上传,头条和广点通通用。2个参数是广点通调用，3个参数头条调用
	 * @zhuxm
	 */
	public static String doFilePost(String url, MultipartEntityBuilder entityBuilder) {
		return doFilePost(url, entityBuilder, null);
	}

	/**
	 * @文件上传,头条和广点通通用。2个参数是广点通调用，3个参数头条调用
	 * @zhuxm
	 */
	@SneakyThrows
	public static String doFilePost(String url, MultipartEntityBuilder entityBuilder, String access_token) {
		// 构造请求
		HttpPost httpPost = new HttpPost(url);
		//文件参数和其他参数：entityBuilder
		HttpEntity entity = entityBuilder.build();
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		try {
			SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(SSLContexts.createDefault(), TLS_VERSION, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			client = HttpClientBuilder.create().setSSLSocketFactory(ssl).build();
			httpPost.setURI(URI.create(url));
			httpPost.setEntity(entity);
			if (StringUtils.isNotBlank(access_token)) {
				httpPost.setHeader("Access-Token", access_token);
			}
			response = client.execute(httpPost);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuilder result = new StringBuilder();
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return result.toString();
			}
		} finally {
			if (response != null) {
				response.close();
			}
			if (null != client) {
				client.close();
			}
		}
		return null;
	}


	public static HttpEntityRequestBuilder getBuilder() {
		return new HttpEntityRequestBuilder().method("GET");
	}

	public static HttpEntityRequestBuilder postBuilder() {
		return new HttpEntityRequestBuilder().method("POST");
	}

	public static HttpEntityRequestBuilder putBuilder() {
		return new HttpEntityRequestBuilder().method("PUT");
	}

	public static HttpEntityRequestBuilder deleteBuilder() {
		return new HttpEntityRequestBuilder().method("DELETE");
	}

	@SneakyThrows
	public static String request(HttpEntityEnclosingRequestBase request) {
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		try {
			SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(SSLContexts.createDefault(), TLS_VERSION, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			client = HttpClientBuilder.create().setSSLSocketFactory(ssl).build();
			response = client.execute(request);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				return EntityUtils.toString(response.getEntity());
			}
		} finally {
			if (null != response) {
				response.close();
			}
			if (null != client) {
				client.close();
			}
		}
		return null;
	}

	private static class HttpGet extends HttpEntityEnclosingRequestBase {

		public final static String METHOD_NAME = "GET";

		public HttpGet() {
			super();
		}

		public HttpGet(URI uri) {
			super();
			setURI(uri);
		}

		public HttpGet(String uri) {
			super();
			setURI(URI.create(uri));
		}

		@Override
		public String getMethod() {
			return METHOD_NAME;
		}

	}

	private static class HttpDelete extends HttpEntityEnclosingRequestBase {

		public final static String METHOD_NAME = "DELETE";

		public HttpDelete() {
			super();
		}

		public HttpDelete(URI uri) {
			super();
			setURI(uri);
		}

		public HttpDelete(String uri) {
			super();
			setURI(URI.create(uri));
		}

		@Override
		public String getMethod() {
			return METHOD_NAME;
		}

	}

	public static class HttpEntityRequestBuilder {

		private final Map<String, String> headers = new HashMap<>(Byte.SIZE);

		private String uri;

		private String method;

		private String contentType;

		private String accessToken;

		private HttpEntity httpEntity;

		private HttpEntityRequestBuilder() {
		}

		public HttpEntityRequestBuilder uri(String uri) {
			this.uri = uri;
			return this;
		}

		public HttpEntityRequestBuilder method(String method) {
			this.method = method;
			return this;
		}

		public HttpEntityRequestBuilder contentType(String contentType) {
			this.contentType = contentType;
			return this;
		}

		public HttpEntityRequestBuilder accessToken(String accessToken) {
			this.accessToken = accessToken;
			return this;
		}

		public HttpEntityRequestBuilder addHeader(String name, String value) {
			headers.put(name, value);
			return this;
		}

		public HttpEntityRequestBuilder httpEntity(HttpEntity httpEntity) {
			this.httpEntity = httpEntity;
			return this;
		}

		public HttpEntityEnclosingRequestBase build() {
			HttpEntityEnclosingRequestBase request;
			if ("GET".equals(method)) {
				request = new HttpGet(uri);
			} else if ("POST".equals(method)) {
				request = new HttpPost(uri);
			} else if ("PUT".equals(method)) {
				request = new HttpPut(uri);
			} else if ("DELETE".equals(method)) {
				request = new HttpDelete(uri);
			} else {
				throw new IllegalArgumentException("未知的method: " + method);
			}
			if (StringUtils.isNotEmpty(contentType)) {
				request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
			}
			if (StringUtils.isNotEmpty(accessToken)) {
				request.setHeader("Access-Token", accessToken);
			}
			headers.forEach(request::setHeader);
			if (null != httpEntity) {
				request.setEntity(httpEntity);
			}
			return request;
		}

		public String request() {
			return OEHttpUtils.request(build());
		}

	}

}
